package tetris;

import java.util.Timer;
import java.util.TimerTask;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar.ButtonData;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class Main extends Application {
	Ellipse[][] cubes = new Ellipse[20][10];
	Rectangle[][] next = new Rectangle[4][4];
	GameData data = new GameData();

	Timer timer = new Timer();
	private boolean started = false;
	Label score = new Label();
	Label level = new Label();
	MediaPlayer audio1;
	MediaPlayer audio2;

	public static void main(String[] args) {
		launch(args);
	}

	/**
	 *
	 * 刷新界面
	 */
	private void render() {

		var datas = data.getBoardData();

		for (int row = 0; row < 20; row++) {
			for (int col = 0; col < 10; col++) {
				var cell = datas[row][col];
				Ellipse cube = cubes[row][col];
				if (!cell.visable) {
					cube.setFill(Color.WHITE);
				} else {
					var c = cell.color;
					Stop[] stops = { new Stop(0, Color.WHITE), new Stop(1, Color.valueOf(c)) };

					RadialGradient gradient = new RadialGradient(0.5, 0.5, 0.5, 0.5, 0.5, true, CycleMethod.NO_CYCLE,
							stops);
					cube.setFill(gradient);
				}
			}
		}

		if (data.getCurrent() == null)
			return;
		var arr = data.getCurrent().getData();

		int sh = data.getCurrent().getHeight();
		int sw = data.getCurrent().getWidth();

		for (int row = 0; row < sh; row++) {
			for (var col = 0; col < sw; col++) {
				if (arr[row][col]) {
					var cube = cubes[data.getCurrent().getTop() + row][data.getCurrent().getLeft() + col];
					var c = data.getCurrent().getColor();

					// cube.setFill(Color.valueOf(c));
					Stop[] stops = { new Stop(0, Color.WHITE), new Stop(1, Color.valueOf(c)) };

					RadialGradient gradient = new RadialGradient(0.5, 0.5, 0.5, 0.5, 0.5, true, CycleMethod.NO_CYCLE,
							stops);
					cube.setFill(gradient);
				}

			}

			for (int i = 0; i < 4; i++) {
				for (int j = 0; j < 4; j++) {
					next[i][j].setFill(
							data.getNext().getData()[i][j] ? Color.valueOf(data.getNext().getColor()) : Color.DARKGRAY);
				}
			}
		}

		Platform.runLater(new Runnable() {
			@Override
			public void run() {
				score.setText(String.format("分数：%d", data.getScore()));
				level.setText(String.format("级别：1", data.getLevel()));

				if (data.isFull()) {
					started = false;

					ButtonType loginButtonType = new ButtonType("OK", ButtonData.OK_DONE);
					Dialog<String> dialog = new Dialog<>();
					dialog.setTitle("Game Over!");
					dialog.setContentText("Game Over!");
					dialog.getDialogPane().getButtonTypes().add(loginButtonType);

					boolean disabled = false; // computed based on content of text fields, for example
					dialog.getDialogPane().lookupButton(loginButtonType).setDisable(disabled);
					dialog.showAndWait();
				}
			}
		});

	}

	@Override
	public void start(Stage primaryStage) throws Exception {

		var audioSrc = getClass().getResource("1.mp3");
		var m = new Media(audioSrc.toString());

		audio1 = new MediaPlayer(m);
		audioSrc = getClass().getResource("2.mp3");
		m = new Media(audioSrc.toString());
		audio2 = new MediaPlayer(m);

		data.setOnRemove(() -> {
			audio2.stop();
			audio2.play();
		});
		// audio1 = AudioSystem.getAudioInputStream(new BufferedInputStream(audioSrc));
		// audio2 = AudioSystem.getAudioInputStream(getClass().getResource("2.mp3"));

		GridPane grid = new GridPane();
		Scene scene = new Scene(grid, 400, 600);

		// primaryStage.initStyle(StageStyle.UTILITY);

		primaryStage.setTitle("My Tetris");
		primaryStage.setScene(scene);
		primaryStage.setOnCloseRequest((e) -> {
			timer.cancel();
		});

		scene.setOnKeyPressed(new EventHandler<KeyEvent>() {

			@Override
			public void handle(KeyEvent e) {

				if (!started)
					return;
				audio1.stop();
				audio1.play();

				switch (e.getCode()) {
				case UP:
					data.changeDirection();
					break;
				case DOWN:
					if (!data.isFull()) {
						data.moveDown();
					}
					break;
				case LEFT:
					data.moveLeft();
					break;
				case RIGHT:
					data.moveRight();
					break;
				case SPACE:
					if (!data.isFull())
						data.drop();
					break;
				default:
					break;
				}
				render();
			}
		});

		BorderPane board = new BorderPane();
		board.setBorder(new Border(new BorderStroke(Color.DARKGRAY, BorderStrokeStyle.SOLID, null, BorderStroke.THIN)));
		board.setPrefSize(300, 600);
		grid.add(board, 0, 0, 1, 3);

		for (int i = 0; i < 20; i++) {
			for (int j = 0; j < 10; j++) {
				Ellipse ellipse = new Ellipse();
				ellipse.setCenterX(j * 30.0f + 15);
				ellipse.setCenterY((19 - i) * 30.0f + 15);
				ellipse.setRadiusX(15);
				ellipse.setRadiusY(15.0f);
				ellipse.setFill(Color.WHITE);
				board.getChildren().add(ellipse);
				cubes[19 - i][j] = ellipse;
			}
		}

		VBox vb0 = new VBox();

		vb0.setPrefHeight(150);
		score.setPrefWidth(98);
		score.setText("分数：0");
		level.setText("级别：1");
		level.setPrefWidth(98);
		vb0.getChildren().add(score);
		vb0.getChildren().add(level);
		vb0.setBackground(new Background(new BackgroundFill(Color.WHITESMOKE, null, null)));
		grid.add(vb0, 1, 0);

		HBox vb1 = new HBox();

		vb1.setPrefHeight(150);

		vb1.setBackground(new Background(new BackgroundFill(Color.WHITESMOKE, null, null)));

		grid.add(vb1, 1, 1);
		BorderPane preview = new BorderPane();

		preview.setBorder(new Border(new BorderStroke(Color.BROWN, BorderStrokeStyle.SOLID, null, BorderStroke.THIN)));
		preview.setPrefSize(98, 150);
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				Rectangle rect = new Rectangle(j * 21 + 2, i * 21 + 2, 20, 20);
				rect.setFill(Color.DARKGRAY);
				next[i][j] = rect;
				preview.getChildren().add(rect);
			}
		}
		vb1.getChildren().add(preview);

		HBox vb = new HBox();
		// vb.setBackground(new Background(Color.ALICEBLUE));
		vb.setAlignment(Pos.BOTTOM_CENTER);
		vb.setId("vbox");

		// vb.setStyle("-fx-fill: red;");
		vb.setBackground(new Background(new BackgroundFill(Color.WHITESMOKE, null, null)));
		vb.setPrefWidth(100);
		Button btn = new Button("Start");
		btn.setFocusTraversable(false);
		btn.setPrefWidth(98);
		btn.setOnMouseClicked((e) -> {
			reset();
			data.randomShape();
			started = true;
			// render();
			timerTask();
		});
//		btn.setId("btn");
		// btn.USE_COMPUTED_SIZE
		vb.getChildren().add(btn);

		grid.setBackground(new Background(new BackgroundFill(Color.ANTIQUEWHITE, null, null)));
		// root.getChildren().add(grid);

		grid.add(vb, 1, 2);
		// grid.getBackground().getFills().add(new BackgroundFill(Color.RED,
		// CornerRadii.EMPTY, Insets.EMPTY));
		primaryStage.centerOnScreen();
		primaryStage.show();
	}

	private void reset() {
		var datas = data.getBoardData();
		for (int row = 0; row < 20; row++) {
			for (int col = 0; col < 10; col++) {
				var cube = datas[row][col];
				cube.visable = false;

			}
		}
	}

	private void timerTask() {
		render();

		timer.schedule(new TimerTask() {

			@Override
			public void run() {
				data.moveDown();
				if (!data.isFull())
					timerTask();

			}
		}, data.getTicks());
	}
}
